package com.zzyl.intercept;

import cn.hutool.json.JSONUtil;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.properties.JwtProperties;
import com.zzyl.utils.JwtUtil;
import com.zzyl.utils.UserThreadLocal;
import com.zzyl.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class AdminUserInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtProperties jwtProp;
    @Autowired
    private StringRedisTemplate redisTemplate;
    /**
     * 获取token解析获取用户id放入Threadlocal
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//        获取请求路径
        String path = request.getRequestURI();
        String method = request.getMethod();
        String targetUrl = method+path;
        log.info("请求路径={}",path);
        log.info("目标路径={}",targetUrl);
//        判断是否登录
        if("/security/login".equals(path)){
//            登录请求,放行
            log.info("当前是登录.path={},放行",path);
            return true;
        }
//        获取token
        String token = request.getHeader("Authorization");
        if(StringUtils.isBlank(token)){
            log.error("token不存在");
            throw new BaseException(BasicEnum.LOGIN_LOSE_EFFICACY);
        }
        try {
//        解析token
            Map<String, Object> claims = JwtUtil.parseJWT(jwtProp.getBase64EncodedSecretKey(), token);
            Object obj = claims.get("currentUser");
            if(obj == null){
                log.error("obj 为空");
                throw new BaseException(BasicEnum.LOGIN_LOSE_EFFICACY);
            }
            UserVo vo = JSONUtil.toBean(obj.toString(), UserVo.class);
            log.info("获取到用户id={}",vo.getId());
//            获取所有的按钮路径
            String str = redisTemplate.opsForValue().get("resource:url");
            if(StringUtils.isBlank(str)){
                log.error("redis中获取不到访问路径");
                throw new BaseException(BasicEnum.USER_ROLE_AND_MENU_EMPTY);
            }
            List<String> allButUrls = JSONUtil.toList(str, String.class);
            boolean isbut = false;
//            创建匹配判断对象
            AntPathMatcher antPathMatcher = new AntPathMatcher();
//            判断当前请求是否是按钮请求
            for (String butUrl : allButUrls) {
//                if(butUrl.equals(targetUrl)){
                if(antPathMatcher.match(butUrl,targetUrl)){
                    log.info("当前请求是按钮请求={}",targetUrl);
                    isbut = true;
                    break;
                }
            }

            if(!isbut){
//                不是按钮路径,就把用户信息放入Theadlocal中,放行
//                  把userid放入ThreadLocal
                log.info("当前请求不是按钮请求={}",targetUrl);
                UserThreadLocal.setSubject(obj.toString());
                return true;
            }else{
                log.info("当前请求是按钮请求={}",targetUrl);
//                判断当前用户是否有权限访问
//            获取当前获取的访问url集合,判断是否可以访问当前路径
            String jsonStr = redisTemplate.opsForValue().get("user:access:url:" + vo.getId());
            if(StringUtils.isBlank(jsonStr)){
                log.error("redis中获取不到访问路径");
                throw new BaseException(BasicEnum.USER_ROLE_AND_MENU_EMPTY);
            }
//            把json转集合
            List<String> urls = JSONUtil.toList(jsonStr, String.class);
            for (String url : urls) {
//                if(url.equals(path)){
                if(antPathMatcher.match(url,targetUrl)){
//                    用户可以访问当前路径
                    log.info("用户可以访问当前路径,url={},targeturl={}",url,targetUrl);
//                  把userid放入ThreadLocal
                    UserThreadLocal.setSubject(obj.toString());
                    return true;
                }
            }
            log.error("用户不能访问当前路径");
            throw new BaseException(BasicEnum.USER_ROLE_AND_MENU_EMPTY);
            }
        }catch (Exception e){
            log.error("token解析失败");
            throw new BaseException(BasicEnum.LOGIN_LOSE_EFFICACY);
        }
    }

    /**
     * 从Threadlocal中清除数据
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //  清除数据
        UserThreadLocal.removeSubject();
    }
}
